<!--**
  *@info 手签名组件
  *@author: thinkmix
  * 需要在html中引入<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
* *-->
<template>
  <section id="signatureBox" class="bgGrey" :class="{active:show}">
    <div class="f-mask" @touchmove.prevent="handle1" @click="onClose"></div>
    <div class="inner">
      <div class="title f-flex mid f-line-btm">
        <div class="auto f-tac">添加手签名</div>
        <div class="clear theme-color" id="clear">清空</div>
      </div>
      <canvas id="signature"></canvas>
      <div class="footer f-line-top">
        <div id="save">保存</div>
        <div class="f-mt-5" id="cancel" @click="onClose">取消</div>
      </div>
    </div>
  </section>
</template>
<script>
import { getWindowWidthAndHeight } from '@/utils/utils';
import hexMD5 from '@/utils/md5';

export default {
  name: 'signature',
  props: {
    show: {
      default: false,
      type: Boolean
    },
    actionUrl: {
      default: '/ums/c/uploadImgFile/upload',
      type: String
    },
    fileType: {
      default: 'Blob', // 数据流
      type: String
    },
    headers: {
      default () {
        return {}
      },
      type: Object
    },
  },
  data () {
    return {
      loading: false,
      layerIndex: 0,
    }
  },
  computed: {

  },
  created () {

  },
  mounted () {
    this.init();
  },
  methods: {
    onClose () {
      if (!this.loading) this.$emit('on-close', false)
    },
    onSave (data, responseText) {
      this.$emit('on-save', data, responseText);
      this.onClose()
    },
    onProgress (event) {
      let temp = '';

      if (event) {
        temp = (event.loaded / event.total * 100).toFixed(0) + '%';
      }

      this.$emit('on-progress', temp);
    },
    init () {
      const vm = this;

      let { windowWidth, windowHeight } = getWindowWidthAndHeight();
      let signatureCanvas = document.getElementById('signature'); // canvas dom对象
      let ratio = Math.max(window.devicePixelRatio || 1, 1); // DPR

      signatureCanvas.height = (windowHeight - 140 - 150) * ratio;

      const signaturePad = new SignaturePad(signatureCanvas, {
        backgroundColor: 'rgba(255, 255, 255, 255)',
        penColor: 'rgb(0, 0, 0)'
      });
      //保存按钮
      document.getElementById('save').addEventListener('click', function (event) {
        // 空
        if (signaturePad.isEmpty()) return;

        var dataURL = signaturePad.toDataURL('image/png');

        vm.onSave(dataURL, {});
        vm.fileUpload(
          vm.actionUrl,
          dataURL,
          (responseText = {}) => {
            vm.layerLoading('end');

            if (responseText.code == '200') {
              vm.onSave('', responseText);
            } else {
              // 使用父级错误气泡
              vm.$parent.errorBubble(responseText);
              vm.onProgress(0);
            }
          }
        )
      });
      //清空按钮
      document.getElementById('clear').addEventListener('click', function (event) {
        signaturePad.clear();
      });

      signatureCanvas.width = signatureCanvas.offsetWidth * ratio;
      signatureCanvas.height = signatureCanvas.offsetHeight * ratio;
      signatureCanvas.getContext("2d").scale(ratio, ratio);
      signaturePad.clear();
    },
    layerLoading (type) {
      switch (type) {
        case 'start':
          this.onProgress(0);
          this.loading = true;
          this.layerIndex = layer.open({ type: 2, shadeClose: false, shade: 'background-color: rgba(255,255,255,0)' });
          break;
        case 'end':
          this.loading = false;
          layer.close(this.layerIndex);
          break;
      }
    },
    async fileUpload (url, dataURL, callback) {
      const vm = this;

      if (vm.loading) return;
      vm.layerLoading('start');

      let { fileData, arrayBufferString } = await vm.dataURLToBlob(dataURL);
      if (!fileData) return;

      let data = new FormData();
      data.append('file', fileData);

      const xhr = new XMLHttpRequest();
      // onload
      xhr.onload = () => {
        let json = xhr.response
        try {
          json = JSON.parse(xhr.responseText)
        } catch (_e) {
          if (xhr.status === 401) {
            json = error('access_denied', xhr.statusText)
          }
        }

        let headers = vm.headersToJSON(xhr.getAllResponseHeaders())
        headers.statusCode = xhr.status
        callback(json || {}, headers)
      }
      // onerror
      xhr.onerror = () => {
        let json = xhr.responseText
        try {
          json = JSON.parse(xhr.responseText)
        } catch (_e) {
          console.error(_e)
        }

        callback(json || error('上传失败'))
      }
      // onprogress
      xhr.upload.onprogress = (event) => {
        if (event.lengthComputable) {
          vm.onProgress(event);
        }
      }

      // open
      xhr.open('POST', url, true);
      // set headers
      // boryaAuth
      let authorization = Object.assign({
        md5: hexMD5(arrayBufferString),
        checkType: '2'
      }, vm.headers);
      let boryaAuth = await vm.getBoryaAuth(authorization);

      xhr.setRequestHeader('Authorization', JSON.stringify(authorization));
      xhr.setRequestHeader('boryaAuth', boryaAuth);
      xhr.withCredentials = true;

      xhr.send(data)
    },
    getBoryaAuth (data) {
      const vm = this;

      return new Promise((resolve) => {
        Jsborya.getAuth({
          data,
          complete: (res) => {
            try {
              let boryaAuth = res.BoryaAuth || res.boryaAuth;

              if (!boryaAuth) {
                throw Error();
              } else {
                resolve(boryaAuth);
              }
            } catch (e) {
              resolve(false)
            }
          }
        })
      })
    },
    headersToJSON (s) {
      var o = {}
      var reg = /([a-z\-]+):\s?(.*);?/gi
      var m = void 0
      while (m = reg.exec(s)) {
        o[m[1]] = m[2]
      }
      return o
    },
    // 
    dataURLToBlob (dataURL) {
      var parts = dataURL.split(';base64,');
      var contentType = parts[0].split(":")[1];
      var raw = window.atob(parts[1]);
      var rawLength = raw.length;
      var arrayBuffer = new Int8Array(rawLength);

      for (var i = 0; i < rawLength; ++i) {
        arrayBuffer[i] = raw.charCodeAt(i);
      }

      let arrayBufferString = arrayBuffer.toString().replace(/,/g, '');
      return new Promise((resolve) => {
        const tempBlob = new File([arrayBuffer], 'sign.png', { type: contentType });

        resolve({
          fileData: tempBlob,
          arrayBufferString
        })
        // const reader = new FileReader();

        // reader.onload = e => {
        //   const res = e.target.result;

        //   console.log(e);
        //   // resolve(res);
        // }

        // reader.readAsArrayBuffer(tempBlob);
      })
    },
    handle1 () {//测试
      alert('11')
    }
  }
}
</script>

<style lang="scss" scoped>
/*签名板*/
#signatureBox {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  opacity: 0;
  transition: opacity 0.2s;
  user-select: none;
  > .inner {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 778;
    width: 100%;
    border-radius: 20px 20px 0 0;
    overflow: hidden;
    background-color: #fff;
    > .title {
      position: relative;
      height: 0.4rem;
      line-height: 0.4rem;
      > .clear {
        position: absolute;
        right: 0;
        top: 0;
        z-index: 1;
        width: 0.7rem;
        text-align: center;
        height: 0.4rem;
        line-height: 0.4rem;
      }
    }
    > canvas {
      background-color: #fff;
      opacity: 1;
      width: 100%;
      outline: none;
    }
    > .footer {
      background-color: #f5f6f7;
      > div {
        background-color: #fff;
        text-align: center;
        padding: 0.15rem 0;
        &:active {
          background-color: #eee;
        }
      }
    }
  }
}
#signatureBox.active {
  z-index: 888;
  opacity: 1;
}
</style>
